package club.xyes.zkh.ecommerce.web.api.controller;

import club.xyes.zkh.ecommerce.commons.entity.Coupon;
import club.xyes.zkh.ecommerce.commons.entity.Shop;
import club.xyes.zkh.ecommerce.commons.exception.BadRequestException;
import club.xyes.zkh.ecommerce.commons.properties.WebsiteConfigurationProperties;
import club.xyes.zkh.ecommerce.commons.util.CouponUtils;
import club.xyes.zkh.ecommerce.commons.util.EntityImagePathUtils;
import club.xyes.zkh.ecommerce.commons.util.TextUtil;
import club.xyes.zkh.ecommerce.commons.vo.GeneralCollectionResult;
import club.xyes.zkh.ecommerce.commons.vo.GeneralResult;
import club.xyes.zkh.ecommerce.service.CouponService;
import club.xyes.zkh.ecommerce.service.ShopService;
import club.xyes.zkh.ecommerce.web.controller.BaseController;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * Create by 郭文梁 2019/4/18 0018 13:44
 * CouponController
 * 优惠券相关数据访问控制器
 *
 * @author 郭文梁
 * @data 2019/4/18 0018
 */
@RestController
@RequestMapping("/api/coupon")
public class CouponController extends BaseController<Coupon> {
    /**
     * 默认优惠券图片
     */
    private static final String DEFAULT_COUPON_IMAGE = "default.png";
    private CouponService service;
    private final ShopService shopService;
    private final WebsiteConfigurationProperties websiteConfigurationProperties;

    @Autowired
    public CouponController(CouponService service,
                            ShopService shopService,
                            WebsiteConfigurationProperties websiteConfigurationProperties) {
        super(service);
        this.service = service;
        this.shopService = shopService;
        this.websiteConfigurationProperties = websiteConfigurationProperties;
    }

    /**
     * 当前用户所拥有的商铺
     *
     * @return 商铺
     */
    private Shop currentShop() {
        return currentShop(shopService);
    }

    /**
     * 创建优惠券
     *
     * @param param 参数
     * @return GR
     */
    @PostMapping("/create")
    @ApiOperation("创建优惠券")
    public GeneralResult<Coupon> create(@RequestBody Coupon param) {
        checkParam(param);
        Shop shop = currentShop();
        Coupon coupon = secureCopy(param, null);
        coupon.setShop(shop);
        coupon.setShopId(shop.getId());
        coupon.setImage(DEFAULT_COUPON_IMAGE);
        Coupon res = service.save(coupon);
        EntityImagePathUtils.prettyCouponImagePath(res, websiteConfigurationProperties.getStaticServerPrefix(),
                websiteConfigurationProperties.getCouponImagePath());
        return GeneralResult.ok(res);
    }

    /**
     * 更新优惠券信息
     *
     * @param id    数据ID
     * @param param 参数
     * @return GR
     */
    @PostMapping("/{id}")
    @ApiOperation("更新优惠券")
    public GeneralResult<Coupon> update(@PathVariable("id") Integer id,
                                        @RequestBody Coupon param) {
        checkParam(param);
        Shop shop = currentShop();
        Coupon coupon = service.getRequired(id);
        if (!Objects.equals(shop.getId(), coupon.getShopId())) {
            return GeneralResult.permissionDenied("您无权操作该数据");
        }
        secureCopy(param, coupon);
        coupon.setShop(shop);
        Coupon res = service.updateById(coupon);
        EntityImagePathUtils.prettyCouponImagePath(res, websiteConfigurationProperties.getStaticServerPrefix(),
                websiteConfigurationProperties.getCouponImagePath());
        return GeneralResult.ok(res);
    }

    /**
     * 获取当前商铺的优惠券
     *
     * @return GR
     */
    @GetMapping("/mine")
    @ApiOperation("获取当前商铺的优惠券")
    public GeneralResult<?> mine() {
        Shop shop = currentShop();
        List<Coupon> coupons = service.findByShop(shop);
        coupons = EntityImagePathUtils.prettyCouponImagePath(coupons,
                websiteConfigurationProperties.getStaticServerPrefix(),
                websiteConfigurationProperties.getCouponImagePath());
        return GeneralCollectionResult.ok(coupons);
    }

    /**
     * 安全拷贝数据
     *
     * @param source 源
     * @return 拷贝
     */
    private Coupon secureCopy(Coupon source, Coupon target) {
        if (target == null) {
            target = new Coupon();
        }
        target.setName(source.getName());
        target.setDiscountWay(source.getDiscountWay());
        target.setStartTime(source.getStartTime());
        target.setEndTime(source.getEndTime());
        target.setMinAmount(source.getMinAmount());
        target.setWeekRangeStart(source.getWeekRangeStart());
        target.setWeekRangeEnd(source.getWeekRangeEnd());
        target.setTimeRangeStart(source.getTimeRangeStart());
        target.setTimeRangeEnd(source.getTimeRangeEnd());
        target.setAmount(source.getAmount());
        target.setDiscountRate(source.getDiscountRate());
        target.setMutualExclusionWithMembershipDiscount(source.getMutualExclusionWithMembershipDiscount());
        target.setDescription(source.getDescription());
        target.setAutoGrant(source.getAutoGrant());
        target.setGrantConditionAmount(source.getGrantConditionAmount());
        return target;
    }

    /**
     * 检查参数
     *
     * @param param 参数
     */
    private void checkParam(Coupon param) {
        if (param == null) {
            throw new BadRequestException("未传参数");
        }
        checkDiscountWay(param);
        checkTime(param);
        if (TextUtil.isTrimedEmpty(param.getName())) {
            throw new BadRequestException("名称不能为空");
        }
        if (TextUtil.isTrimedEmpty(param.getMinAmount())) {
            throw new BadRequestException("未指定最低使用金额");
        }
        if (TextUtil.isTrimedEmpty(param.getAmount())) {
            throw new BadRequestException("未指定优惠金额");
        }
        if (param.getMutualExclusionWithMembershipDiscount() == null) {
            throw new BadRequestException("未指定和会员优惠是否冲突");
        }
    }

    /**
     * 检查约束时间
     *
     * @param param 参数
     */
    private void checkTime(Coupon param) {
        Date startTime = param.getStartTime();
        Date endTime = param.getEndTime();
        if (startTime == null || endTime == null) {
            throw new BadRequestException("未指定有效时间");
        }
        if (endTime.getTime() - startTime.getTime() < 0) {
            throw new BadRequestException("有效时间不合法");
        }
        Integer weekRangeStart = param.getWeekRangeStart();
        Integer weekRangeEnd = param.getWeekRangeEnd();
        if (weekRangeEnd == null || weekRangeStart == null) {
            throw new BadRequestException("星期时间区间不能为空");
        }
        if (weekRangeEnd - weekRangeStart < 0) {
            throw new BadRequestException("无效的星期区间");
        }
        Date timeRangeStart = param.getTimeRangeStart();
        Date timeRangeEnd = param.getTimeRangeEnd();
        if (timeRangeEnd == null || timeRangeStart == null) {
            throw new BadRequestException("未指定使用时间区间");
        }
        if (timeRangeEnd.getTime() - timeRangeStart.getTime() < 0) {
            throw new BadRequestException("无效的使用时间区间");
        }
    }

    /**
     * 检查优惠券方式是否合法
     *
     * @param coupon 参数
     */
    private void checkDiscountWay(Coupon coupon) {
        Integer discountWay = coupon.getDiscountWay();
        if (discountWay == null) {
            throw new BadRequestException("优惠方式不能为空");
        }
        Double discountRate;
        try {
            discountRate = Double.parseDouble(coupon.getDiscountRate());
        } catch (Exception e) {
            discountRate = null;
        }
        Integer amount;
        try {
            amount = Integer.parseInt(coupon.getAmount());
        } catch (Exception e) {
            amount = null;
        }
        switch (discountWay) {
            case Coupon.DISCOUNT_CASH_COUPON:
                if (amount == null) {
                    throw new BadRequestException("优惠金额不能为空");
                }
                break;
            case Coupon.DISCOUNT_DISCOUNT_COUPON:
                if (discountRate == null) {
                    throw new BadRequestException("折扣率不能为空");
                }
                break;
            default:
                throw new BadRequestException("折扣方式 " + discountRate + " 不合法");
        }
    }

    /**
     * 设置优惠券图片
     *
     * @param id        ID
     * @param imageFile 图片文件
     * @return GR
     * @throws IOException IO异常
     */
    @ApiOperation("设置优惠券图片")
    @PostMapping("/{id}/set-image")
    public GeneralResult<Coupon> setImage(@PathVariable("id") Integer id,
                                          MultipartFile imageFile) throws IOException {
        if (imageFile == null || imageFile.isEmpty()) {
            return GeneralResult.badRequest("未上传图片");
        }
        Coupon coupon = service.getRequired(id);
        Shop shop = currentShop();
        if (!Objects.equals(shop.getId(), coupon.getShopId())) {
            return GeneralResult.permissionDenied("您无权操作该数据");
        }
        Coupon res = service.setImage(coupon, imageFile);
        EntityImagePathUtils.prettyCouponImagePath(res,
                websiteConfigurationProperties.getStaticServerPrefix(),
                websiteConfigurationProperties.getCouponImagePath());
        return GeneralResult.ok(res);
    }

    /**
     * 根据商铺ID查询优惠券
     *
     * @param shopId 商铺ID
     * @return GCR
     */
    @ApiOperation("根据商铺ID查询优惠券")
    @GetMapping("/shop/{shopId}")
    public GeneralCollectionResult<Coupon> findByShopId(@PathVariable("shopId") Integer shopId) {
        Shop shop = shopService.getRequired(shopId);
        List<Coupon> coupons = service.findByShop(shop).stream().filter(CouponUtils::checkAvailable).collect(Collectors.toList());
        coupons = EntityImagePathUtils.prettyCouponImagePath(coupons,
                websiteConfigurationProperties.getStaticServerPrefix(),
                websiteConfigurationProperties.getCouponImagePath());
        return GeneralCollectionResult.ok(coupons);
    }

    /**
     * 通过状态查询商铺的优惠券
     *
     * @param state 状态
     * @return GR
     */
    @ApiOperation("通过状态查询商铺的优惠券")
    @GetMapping("/by-current-shop")
    public GeneralResult<List<Coupon>> findByShopAndState(@RequestParam("state") String state) {
        Shop shop = currentShop();
        List<Coupon> coupons;
        switch (state) {
            case "available":
                coupons = service.findAvailableByShop(shop);
                break;
            case "expired":
                coupons = service.findExpiredByShop(shop);
                break;
            default:
                return GeneralResult.badRequest("unknown state :" + state);
        }
        String serverPrefix = websiteConfigurationProperties.getStaticServerPrefix();
        String path = websiteConfigurationProperties.getCouponImagePath();
        coupons = EntityImagePathUtils.prettyCouponImagePath(coupons, serverPrefix, path);
        return GeneralResult.ok(coupons);
    }

    /**
     * 使优惠券实现
     *
     * @param id ID
     * @return GR
     */
    @ApiOperation("使优惠券失效")
    @PostMapping("/{id}/invalidate")
    public GeneralResult<Coupon> invalidate(@PathVariable("id") Integer id) {
        Coupon coupon = service.getRequired(id);
        coupon.setEndTime(new Date(0));
        Coupon res = service.updateById(coupon);
        return GeneralResult.ok(res);
    }
}
